package entity

import (
	"bytes"
	"fmt"
)

type Set[T comparable, V any] map[T]V

// NewSet 创建set
func NewSet[T comparable, V any](elements ...T) Set[T, V] {
	s := Set[T, V]{}
	for _, e := range elements {
		s.Add(e)
	}
	return s
}
func (r *Set[T, V]) Len() int {
	return len(*r)
}

func (r *Set[T, V]) Add(elements ...T) {
	for _, v := range elements {
		var vs V
		(*r)[v] = vs
	}
}
func (r *Set[T, V]) AddKV(elements T, v V) {
	(*r)[elements] = v
}

// AddSetSelf 合并，后替换前
func (r *Set[T, V]) AddSetSelf(anotherSet Set[T, V]) {
	for ele, v := range anotherSet {
		r.AddKV(ele, v)
	}
}
func (r *Set[T, V]) AddSet(anotherSet Set[T, V]) Set[T, V] {
	retSet := NewSet[T, V]()
	for ele, v := range anotherSet {
		retSet.AddKV(ele, v)
	}
	return retSet
}

// 无脑加，后替换前
func (r *Set[T, V]) AddMapSelf(anotherMap map[T]V) {
	for k, v := range anotherMap {
		r.AddKV(k, v)
	}
}
func (r *Set[T, V]) Del(elements ...T) {
	for _, v := range elements {
		delete(*r, v)
	}
}
func (r *Set[T, V]) Contain(element T) bool {
	_, ok := (*r)[element]
	return ok
}

// IntersectSlice 获取 数组与map共同的元素
func (r *Set[T, V]) IntersectSlice(anotherSet ...T) Set[T, V] {
	retSet := NewSet[T, V]()
	for _, ele := range anotherSet {
		if _, ok := (*r)[ele]; ok {
			retSet.Add(ele)
		}
	}
	return retSet
}

// IntersectSet 取交集
func (r *Set[T, V]) IntersectSet(anotherSet Set[T, V]) Set[T, V] {
	retSet := NewSet[T, V]()
	for ele := range *r {
		if v, ok := anotherSet[ele]; ok {
			retSet.AddKV(ele, v)
		}
	}
	return retSet
}

// DiffSet IntersectSet 取差集
func (r *Set[T, V]) DiffSet(anotherSet Set[T, V]) Set[T, V] {
	retSet := NewSet[T, V]()
	for key, value := range *r {
		if _, ok := anotherSet[key]; !ok {
			retSet.AddKV(key, value)
		}
	}
	return retSet
}

// ToSlice 获取所有元素的列表
func (r *Set[T, V]) ToSlice() []T {
	var retList []T
	//retList := make([]T, len(*r))
	for ele := range *r {
		retList = append(retList, ele)
	}
	return retList
}

// ToString ToSlice 获取所有元素的列表
func (r *Set[T, V]) ToString(separator string) string {
	var bt bytes.Buffer
	var count = 0
	for ele := range *r {
		bt.WriteString(fmt.Sprint(ele))
		if count < r.Len() {
			bt.WriteString(separator)
		}
	}
	return bt.String()
}

// map 的key 转set (忽略value)
func MapKeyToSet[T comparable, V any](m map[T]V) Set[T, V] {
	set := NewSet[T, V]()
	for t, v := range m {
		set.AddKV(t, v)
	}
	return set
}

// map value 转set (忽略value)
func MapReverse[T comparable, V comparable](m map[T]V) Set[V, T] {
	set := NewSet[V, T]()
	for k, v := range m {
		set.AddKV(v, k)
	}
	return set
}
